package com.smileus.integration.caller;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;
import com.ibatis.common.util.Page;
import com.smileus.common.CallInfo;
import com.smileus.common.Env;
import com.smileus.common.OneTask;
import com.smileus.common.Param;
import com.smileus.integration.cluster.divert.Diverter;
import com.smileus.util.JSONUtil;

/**
 * 异步批量调用模式
 * 
 * @author dongheng
 */
public class AsyncBatchServiceCaller {
	private static final Logger logger = Logger.getLogger(AsyncBatchServiceCaller.class);
	private static AtomicLong seq = new AtomicLong(0);
	private static Diverter diverter = Env.getBean("diverter", Diverter.class);

	/**
	 * 获取完整调用结果 * serviceId形式如：userService.add，userService为当前机器上spring bean
	 * id，add为当前bean的方法；
	 * 
	 * @param serviceId
	 * @param param数组
	 *            ，注意参数顺序
	 * @return
	 */
	public static String callFullResult(String serviceId, Param... params) {
		String result = null;
		try {
			long start = System.currentTimeMillis();
			Long myseq = seq.getAndIncrement();
			CallInfo callInfo = diverter.assemCallInfo(serviceId, params);
			OneTask oneTask = new OneTask();
			oneTask.setCallInfo(callInfo);
			oneTask.setSeq(myseq);// 这个值将传给服务器端
			GeneralBatchCaller.putTask(callInfo.getUrl(), oneTask);// 放到任务队列
			result = GeneralBatchCaller.getOneTaskResult(myseq);
			System.out.println(serviceId + "获取结果:" + myseq + "花的毫秒数:" + (System.currentTimeMillis() - start));
		} catch (Exception e) {
			logger.error(e);
			// 调用异常处理..todo
			throw new RuntimeException(e);
		}
		return result;
	}

	/**
	 * 由于目标类型为list和page等类型是，处理不一样，该方法暂时不对外公开 获取字符串结果
	 * 
	 * @param serviceId
	 * @param param
	 * @return String
	 * @throws
	 */
	private static <T> T callForTarget(String serviceId, Class<T> targetClass, Param... params) {
		String fullResult = callFullResult(serviceId, params);
		JSONObject json = JSONObject.parseObject(fullResult);
		if (json.getBoolean("success")) {
			return JSONUtil.toTarget(json.getString("result"), targetClass);
		} else {
			throw new RuntimeException("获取结果出错：" + json.getString("desc"));
		}
	}

	public static BigDecimal callForBigDecimal(String serviceId, Param... params) {
		return callForTarget(serviceId, BigDecimal.class, params);
	}

	public static BigInteger callForBigInteger(String serviceId, Param... params) {
		return callForTarget(serviceId, BigInteger.class, params);
	}

	public static Date callForDate(String serviceId, Param... params) {
		return callForTarget(serviceId, Date.class, params);
	}

	public static Boolean callForBoolean(String serviceId, Param... params) {
		return callForTarget(serviceId, Boolean.class, params);
	}

	public static Character callForCharacter(String serviceId, Param... params) {
		return callForTarget(serviceId, Character.class, params);
	}

	public static Byte callForByte(String serviceId, Param... params) {
		return callForTarget(serviceId, Byte.class, params);
	}

	public static Short callForShort(String serviceId, Param... params) {
		return callForTarget(serviceId, Short.class, params);
	}

	public static String callForString(String serviceId, Param... params) {
		return callForTarget(serviceId, String.class, params);
	}

	public static Integer callForInteger(String serviceId, Param... params) {
		return callForTarget(serviceId, Integer.class, params);
	}

	public static Long callForLong(String serviceId, Param... params) {
		return callForTarget(serviceId, Long.class, params);
	}

	public static Float callForFloat(String serviceId, Param... params) {
		return callForTarget(serviceId, Float.class, params);
	}

	/**
	 * 获取JSONObject结果
	 * 
	 * @param serviceId
	 * @param param
	 * @return JSONObject
	 * @throws
	 */

	public static JSONObject callForJSON(String serviceId, Param... params) {
		String jsonStr = callForString(serviceId, params);
		return JSONUtil.toEntity(jsonStr, JSONObject.class);
	}

	/**
	 *获取指定类型的结果
	 * 
	 * @param <T>
	 * @param serviceId
	 * @param param
	 * @param targetClass
	 * @return T
	 * @throws
	 */
	public static <T> T callForEntity(String serviceId, Class<T> targetClass, Param... params) {
		String jsonString = callForString(serviceId, params);
		return JSONUtil.toEntity(jsonString, targetClass);
	}

	/**
	 * 获取指定类型的List
	 * 
	 * @param <T>
	 * @param serviceId
	 * @param param
	 * @param targetClass
	 * @return T
	 * @throws
	 */
	public static <T> List<T> callForList(String serviceId, Class<T> targetClass, Param... params) {
		String str = callForString(serviceId, params);
		return JSONUtil.toList(str, targetClass);
	}

	/**
	 * 获取分页结果
	 * 
	 * @param <T>
	 * @param serviceId
	 * @param param
	 * @param targetClass
	 * @return T
	 * @throws
	 */
	@SuppressWarnings("unchecked")
	public static <T> Page<T> callForPage(String serviceId, Class<T> targetClass, Param... params) {
		Page<T> result = null;
		List resultList = null;
		try {
			result = callForEntity(serviceId, Page.class, params);
			resultList = result.getResult();
			result.setResult(JSONUtil.toList(resultList, targetClass));
		} catch (Exception e) {
			logger.error(e);
			// 调用异常处理..todo
			throw new RuntimeException(e);
		}
		return result;
	}
}
